#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/sem.h>
#include <sys/ipc.h>
#include <inttypes.h>
#include <time.h>
#include <genrand.h>
#include <hexstr.h>
#include <dlfcn.h>

#define FUNC_TYPE_DEFINE 0

int main(int argsize, const char **args)
{
    // 参数mode：　打开方式，有以下选项
    // RTLD_DEEPBIND -- 动态库里的函数优先调用本动态库的符号，优先级甚至高于LD_PRELOAD
    // RTLD_LAZY -- 等有需要时才解析出符号，所以如果有未定义的符号,在没调用之前也不执行解析
    // RTLD_NOW -- 在dlopen返回前，解析出所有的未定义符号，如果解析不出来，返回NULL
    // RTLD_GLOBAL 动态库中符号表全局打开，因此符号可被其后打开的其它库重定位
    // RTLD_LOCAL  与RTLD_GLOBAL作用相反，动态库中符号表非全局打开，定义的符号不能被其后打开的其它库重定位
    
    // void *tmphand = dlopen("./libsrc/libadd.so-err", RTLD_NOW);
    void *tmphand = dlopen("./libsrc/libadd.so", RTLD_NOW);
    if (!tmphand)
    {
        printf("open dl fail:%s\n", dlerror());
        return -1;
    }
#if FUNC_TYPE_DEFINE == 1
    typedef int (*addtype)(float a, float b);
#elif FUNC_TYPE_DEFINE == 2
    typedef int (*addtype)(int a, int b, int c);
#elif FUNC_TYPE_DEFINE == 3
    typedef int (*addtype)(int a);
#else
    typedef int (*addtype)(int a, int b);
#endif
    // dlsym 不能判断参数个数和类型。使用要明确函数声明。
    addtype tmpfunc = dlsym(tmphand, "addfunc");
    if (!tmpfunc)
    {
        printf("get dl func fail:%s\n", dlerror());
        goto finishPointer;
    }
#if FUNC_TYPE_DEFINE == 1
    printf("add lib = %d\n", tmpfunc(1000, 5));
#elif FUNC_TYPE_DEFINE == 2
    printf("add lib = %d\n", tmpfunc(1000, 5, 7));
#elif FUNC_TYPE_DEFINE == 3
    printf("add lib = %d\n", tmpfunc(1000));
#else
    printf("add lib = %d\n", tmpfunc(1000, 5));
#endif
finishPointer:
    dlclose(tmphand);
    return 1;
}